package com.smit.common;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.HttpHandler;
import com.lidroid.xutils.http.RequestParams;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.lidroid.xutils.http.client.HttpRequest;
import com.smit.bean.UpdatePackageBean;
import com.smit.utils.MD5Util;
import com.smit.utils.SharePrefUtil;
import com.smit.utils.StrUtil;

import java.io.File;
import java.io.IOException;
import java.util.Locale;

public class UpdateManager {
    static String TAG = "UpdateManager";
    private Context context;
    private boolean isDownloading = false;
    private HttpHandler httpHandler = null;
    private String downloadDir = Environment.getExternalStorageDirectory().getAbsolutePath();
    private String downloadPath = downloadDir + "/update.zip";
    private JSONObject updateInfoJson = null;
    private UpdatePackageBean updatePackageInfo = null;
    private static UpdateManager instance = new UpdateManager();


    private BroadcastReceiver batteryLevelReceiver;
    private boolean isBatteryLevelLow = true;
    private boolean isNeedUpdate = false;
    private boolean isNeedConfirm = true;
    private String updateFilePath = downloadPath;
    private boolean hasReceived = false;
    private boolean hasRegistered = false;
    private boolean hasDownloaded = false;

    /**
     * @param context 用android application context，不要用activity的，否则出现内存泄漏。
     * @return
     */
    public static UpdateManager getInstance(Context context) {
        instance.context = context;
        instance.checkBattery();
        return instance;
    }

    public void checkUpdate(final RequestCallBack<String> requestCallBack) {
        final int nowVersionCode = 12;//从系统获取
        String nowVersionName = "v1.0.1";//从系统获取
        String deviceSn = "ABCD";//从系统获取
        String operatorCode = "URUMQI_BANK";//从系统获取
        String productCode = "SM40v1";//从系统获取

        // http://pay.smit.com.cn/smitup/do/update/check/firmware
        // ?device_sn=ABCD&operator_code=URUMQI_BANK&product_code=SM40v1
        // &software_version_name=v1.0.8&software_version_code=12
        RequestParams params = new RequestParams();
        params.addQueryStringParameter("software_version_code", nowVersionCode + "");
        params.addQueryStringParameter("software_version_name", nowVersionName);
        params.addQueryStringParameter("device_sn", deviceSn);
        params.addQueryStringParameter("operator_code", operatorCode);
        params.addQueryStringParameter("product_code", "SM40v1");

        String serverUrl = SharePrefUtil.getString(context, SharePrefUtil.SERVER_URL_KEY, SharePrefUtil.defaultServerUrl);
        HttpUtils http = new HttpUtils();
        http.send(HttpRequest.HttpMethod.POST,
                serverUrl,
                params,
                new RequestCallBack<String>() {

                    @Override
                    public void onStart() {
                        requestCallBack.onStart();
                    }

                    @Override
                    public void onLoading(long total, long current, boolean isUploading) {
                        requestCallBack.onLoading(total, current, isUploading);
                    }

                    @Override
                    public void onSuccess(ResponseInfo<String> responseInfo) {
                        updateInfoJson = JSON.parseObject(responseInfo.result);
                        if (updateInfoJson.getJSONArray("packages").size() > 0) {
                            JSONObject object = updateInfoJson.getJSONArray("packages").getJSONObject(0);//默认用第1个来做，其他情况不考虑
                            updatePackageInfo = JSON.parseObject(object.toJSONString(), UpdatePackageBean.class);
                        }
                        requestCallBack.onSuccess(responseInfo);
                    }

                    @Override
                    public void onFailure(HttpException error, String msg) {
                        requestCallBack.onFailure(error, msg);
                    }
                });
    }

    public void downloadFile(final RequestCallBack<File> requestCallBack) {
        String url = updatePackageInfo.getUrl();
        if (url == null || url.length() == 0) {
            Log.d(TAG, "download url is null or empty");
            return;
        }
        HttpUtils httpUtils = new HttpUtils();
        downloadPath = downloadDir + "/" + updatePackageInfo.getFilename();
        //没有下载时点击,进行下载
        if (!isDownloading) {
            isDownloading = true;
            //参数:下载地址，文件存储路径，是否断点续传，是否重命名，请求回调
            httpHandler = httpUtils.download(url, downloadPath, true, true, new RequestCallBack<File>() {
                @Override
                public void onStart() {
                    requestCallBack.onStart();
                }

                @Override
                public void onLoading(long total, long current, boolean isUploading) {
                    String currentSize = StrUtil.getFileSizeStr(current);
                    String totalSize = StrUtil.getFileSizeStr(total);
                    String percentStr = String.format(Locale.getDefault(), "%d%%", current * 100 / total);
                    String msg = percentStr + "  " + currentSize + "/" + totalSize;
                    Log.d(TAG, "update file downloaded " + msg);
                    requestCallBack.onLoading(total, current, isUploading);
                }

                @Override
                public void onSuccess(ResponseInfo<File> responseInfo) {
                    File file = new File(downloadPath);
                    if (!file.exists()) {
                        Log.d(TAG, "download file is not exist");
                        return;
                    }
                    try {
                        String md5 = MD5Util.getFileMD5String(file);
                        if (updatePackageInfo.getMd5().equalsIgnoreCase(md5)) {
                            SharePrefUtil.saveString(context, SharePrefUtil.DOWNLOAD_FILE_PATH, downloadPath);
                            hasDownloaded = true;
                            requestCallBack.onSuccess(responseInfo);
                        } else {
                            String msg = "file md5 check fail";
                            HttpException error = new HttpException(msg);
                            requestCallBack.onFailure(error, msg);
                            if(!file.delete()){
                                file.deleteOnExit();
                            }
                            Log.d(TAG, msg);
                        }
                    } catch (IOException e) {
                        String msg = e.getMessage();
                        HttpException error = new HttpException(msg);
                        requestCallBack.onFailure(error, msg);
                        Log.d(TAG, msg);
                        e.printStackTrace();
                    }
                }

                @Override
                public void onFailure(HttpException error, String msg) {
                    long downloadSize = 0;
                    File file = new File(downloadPath);
                    if (file.exists()) {
                        downloadSize = file.length();
                    }
                    if (updatePackageInfo.getSize() == downloadSize) {
                        Log.d(TAG, "file has downloaded");
                        ResponseInfo<File> responseInfo = new ResponseInfo<File>(null, file, true);
                        hasDownloaded = true;
                        requestCallBack.onSuccess(responseInfo);
                        return;
                    }
                    Log.d(TAG, "file download failed");
                    requestCallBack.onFailure(error, msg);
                }
            });
        }
    }

    public void cancelDownload() {
        if (httpHandler != null && isDownloading) {
            httpHandler.cancel();
            isDownloading = false;
        }
    }

    public UpdatePackageBean getUpdatePackageBean() {
        return updatePackageInfo;

    }

    public JSONObject getUpdateJson() {
        return updateInfoJson;
    }

    public String getUpdateFilePath() {
        return updateFilePath;
    }

    public boolean getIsDownloading() {
        return isDownloading;
    }

    public String getDownloadPath() {
        return downloadPath;
    }

    public boolean getHasDownloaded() {
        return hasDownloaded;
    }

    public void startOSUpdate(String filePath, boolean confirm) {
        isNeedConfirm = confirm;
        isNeedUpdate = true;
        updateFilePath = filePath;
        if (isBatteryLevelLow) {
            if (hasReceived) {//这里可能电池电量检测还没完成
                Log.d(TAG, "battery level is low");
                Toast.makeText(context, "电池电量低于50%，不能升级！", Toast.LENGTH_LONG).show();
            } else {
                Log.d(TAG, "battery broadcast has not received");
            }
            return;
        }

        Intent it = new Intent("com.qualcomm.update.REBOOT");
        it.setData(Uri.fromFile(new File(filePath)));
        it.putExtra("update_confirm", confirm); //升级前是否弹框确认升级
        it.putExtra("update_verify", true);//升级前是否校验升级包
        it.putExtra("update_mode", 2);
        it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(it);
        isNeedUpdate = false;
    }

    private void checkBattery() {
        if (hasRegistered) {
            Log.d(TAG, "battery receiver has registered");
            return;
        }
        batteryLevelReceiver = new BroadcastReceiver() {
            public void onReceive(Context context, Intent intent) {
                hasReceived = true;
                StringBuilder sb = new StringBuilder();
                int rawlevel = intent.getIntExtra("level", -1);
                int scale = intent.getIntExtra("scale", -1);
                int status = intent.getIntExtra("status", -1);
                int health = intent.getIntExtra("health", -1);
                int level = -1; // percentage, or -1 for unknown
                if (rawlevel >= 0 && scale > 0) {
                    level = (rawlevel * 100) / scale;
                }
                if (level > 50) {
                    isBatteryLevelLow = false;
                } else {
                    isBatteryLevelLow = true;
                }
                sb.append("\nthe device battery rawlevel=" + rawlevel + " scale=" + scale + " status=" + status);
                if (BatteryManager.BATTERY_HEALTH_OVERHEAT == health) {
                    sb.append("'s battery feels very hot!");
                } else {
                    switch (status) {
                        case BatteryManager.BATTERY_STATUS_UNKNOWN:
                            sb.append("no battery.");
                            break;
                        case BatteryManager.BATTERY_STATUS_CHARGING:
                            isBatteryLevelLow = false;
                            sb.append("'s battery");
                            if (level <= 33)
                                sb.append(" is charging, battery level is low"
                                        + "[" + level + "]");
                            else if (level <= 84)
                                sb.append(" is charging." + "[" + level + "]");
                            else
                                sb.append(" will be fully charged.");
                            break;
                        case BatteryManager.BATTERY_STATUS_DISCHARGING:
                        case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
                            if (level == 0)
                                sb.append(" needs charging right away.");
                            else if (level > 0 && level <= 33)
                                sb.append(" is about ready to be recharged, battery level is low"
                                        + "[" + level + "]");
                            else
                                sb.append("'s battery level is" + "[" + level + "]");
                            break;
                        case BatteryManager.BATTERY_STATUS_FULL:
                            isBatteryLevelLow = false;
                            sb.append(" is fully charged.");
                            break;
                        default:
                            sb.append("'s battery is indescribable!");
                            break;
                    }
                }
                Log.d(TAG, sb.toString());
                if (isNeedUpdate && !isBatteryLevelLow) {
                    startOSUpdate(updateFilePath, isNeedConfirm);
                }
            }
        };
        IntentFilter batteryLevelFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        context.registerReceiver(batteryLevelReceiver, batteryLevelFilter);
        hasRegistered = true;
    }

    private UpdateManager() {
    }
}
 /*
{
    "deviceSn": "ABCD",
        "productCode": "SM40v1",
        "operatorCode": "URUMQI_BANK",
        "softwareVersionName": "v1.0.1",
        "softwareVersionCode": 12,
        "packages": [
        {
            "type": "entire",
                "fromVersion": "*",
                "toVersion": "v1.0.31",
                "url": "http://pay.smit.com.cn:80/fs/2017/02/10/2b5164053e3b45618fffb61d7cb062ed.zip",
                "md5": "6628e67b86a919a901837ad007bcb9bf",
                "size": 1350591,
                "filename": "OTA_v1.0.31.zip",
                "description": "整包升级"
        }
        ]
}
*/